<?php
use think\Route;
use think\Config;
use think\Db;
use think\db\Expression;
use think\paginator\driver\Bootstrap;

ini_set('display_errors', 'Off'); // 避免重复报错
error_reporting(E_ALL);

define('USER_AGENT_IE',     'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');
define('USER_AGENT_CHROME', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36');
define('USER_AGENT_IPHONE', 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1');

// 从字串 $src 中提取 特征码为$begin 到 特征码为$end 之间的字串, $include 表示是否包含特征码返回
function str_extract($src, $begin, $end, $include = false) {
  $i = strpos($src, $begin);
  if($i!==false){
    $j = strpos($src, $end, $i);
    if($j!==false){
      if($include){
        return substr($src, $i, $j-$i+strlen($end));
      }else{
        $a = strlen($begin);
        return substr($src, $i+$a, $j-$i-$a);
      }
    }
  }
  return '';
}
/**
 *  @brief  : curl精简封装
 *  @return : array
 *  @details:
 */
//function curl($opts = []) {
//  $ch = curl_init();
//  $opts = $opts + [
//    CURLOPT_ENCODING => 'gzip, deflate',
//    CURLOPT_RETURNTRANSFER => true,
//  ];
//  curl_setopt_array($ch, $opts);
//  $data = curl_exec($ch);
//  $retn = ['error' => curl_error($ch), 'errno' => curl_errno($ch), 'info' => curl_getinfo($ch), 'data' => $data];
//  curl_close($ch);
//  return $retn;
//}

/**
 *  @brief  : curl_http    Get()精简封装
 *  @return : array
 *  @details:
 */
function curl_http($url = []) {

    $ch = curl_init();//初始化
    /*============开始设置curl各种选项================*/
    $opts = $url + [
            CURLOPT_ENCODING => 'gzip, deflate',
            CURLOPT_RETURNTRANSFER=>1,
        ];
    curl_setopt_array($ch, $opts);
    $html = curl_exec($ch);//执行句柄，获取返回内容
    $retn = ['error' => curl_error($ch), 'errno' => curl_errno($ch), 'info' => curl_getinfo($ch), 'data' => $html];
    curl_close($ch);//释放句柄
    return $retn;
}

/**
 *  @brief  : http_curl    POST()封装
 *  @return : json
 *  @details:
 */

function http_curl($url,$opt_data){
//    $url = 'http://localhost/3.php';
//    $opt_data = 'name=BY2&age=999&sex=MAXMAN';

    $curl = curl_init();  //初始化
    curl_setopt($curl,CURLOPT_URL,$url);  //设置url
    curl_setopt($curl,CURLOPT_HTTPAUTH,CURLAUTH_BASIC);  //设置http验证方法
    curl_setopt($curl,CURLOPT_HEADER,0);  //设置头信息
    curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);  //设置curl_exec获取的信息的返回方式
    curl_setopt($curl,CURLOPT_POST,1);  //设置发送方式为post请求
    curl_setopt($curl,CURLOPT_POSTFIELDS,$opt_data);  //设置post的数据

    $result = curl_exec($curl);
    if($result === false){
        echo curl_errno($curl);
        exit();
    }
    print_r($result);
    curl_close($curl);

}



/**
+----------------------------------------------------------------------------------------
* 以16进制逐字节打印出来
+----------------------------------------------------------------------------------------
*/
function print_hex($val, $prefix='0x', $print=true){
  $ret = '';
  $eax = unpack('H*', $val);
  if(count($eax)==1 && array_key_exists(1, $eax)){
    $eax = strtoupper($eax[1]);
    $eax = chunk_split($eax, 2, ',');
    $ret = rtrim($eax, ',');
    if(!empty($prefix)){
      $ret = explode(',', $ret);
      foreach($ret as $k=>&$v){
        $v = '0x'.$v;
      }
      $ret = implode(',', $ret);
    }
  }
  if($print){
    $ret = explode(',', $ret);
    $ret = array_chunk($ret, 8);
    $b = array();

    foreach($ret as $a){
      $b[] = implode(',', $a);
    }
    $ret = implode(",\n", $b);
    echo($ret."\n");
  }else{
    return $ret;
  }
}
/**
 * 生成UUID 单机使用
 * @access public
 * @return string
 */
function uuid() {
  $s = md5(uniqid(mt_rand(), true));
  $a = substr($s, 0, 8);
  $b = substr($s, 8, 4);
  $c = substr($s, 12, 4);
  $d = substr($s, 16, 4);
  $e = substr($s, 20, 12);
  return "{{$a}-{$b}-{$c}-{$d}-{$e}}";
}
// 返回"2017-6-27 16:01:12", 用于模型 $_auto
function YmdHis($timestamp = 0) {
  return date('Y-m-d H:i:s', $timestamp > 0 ? $timestamp : time());
}
/**
 *  @brief  : 将'Y-m-d H:i:s'或'Y-m-d'格式的时间转换成`Unix`时间戳
 *  @param [in] $YmdHis : 'Y-m-d H:i:s'或'Y-m-d'格式的时间
 *  @return : 失败返回0, 成功返回正整数
 *  @details: 因为`strtotime`有bug!
 *  '2017-06-23 03:03:18'  => 1498186998
 */
function YmdHis2Unix($YmdHis) {
  $eax = sscanf($YmdHis, '%04d-%02d-%02d %02d:%02d:%02d', $Y, $m, $d, $H, $i, $s);
  if ($eax === 6) { // 'Y-m-d H:i:s'
    $eax = mktime($H, $i, $s, $m, $d, $Y);
  } else if ($eax === 3) { // 'Y-m-d'
    $eax = mktime(0, 0, 0, $m, $d, $Y);
  } else {
    $eax = 0;
  }
  return $eax;
}
/**
 * 把返回的数据集转换成Tree
 * @param array $list 要转换的数据集
 * @param string $pid parent标记字段
 * @param string $level level标记字段
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function list_to_tree($list, $pk='id', $pid = 'pid', $child = '_child', $root = 0) {
  // 创建Tree
  $tree = array();
  if(is_array($list)) {
    // 创建基于主键的数组引用
    $refer = array();
    foreach ($list as $key => $data) {
      $refer[$data[$pk]] =& $list[$key];
    }
    foreach ($list as $key => $data) {
      // 判断是否存在parent
      $parentId =  $data[$pid];
      if ($root == $parentId) {
        $tree[] =& $list[$key];
      }else{
        if (isset($refer[$parentId])) {
          $parent =& $refer[$parentId];
          $parent[$child][] =& $list[$key];
        }
      }
    }
  }
  return $tree;
}

function redis($conf = []) {
  static $_instance = [];
  
  $conf = empty($conf) ? Config::get('redis') : $conf;
  $conf = is_string($conf) ? (Config::get('redis', trim($conf, '.')) ?  : []) : $conf;

  $conf = array_merge([
    'hostname'    => '127.0.0.1',
    'hostport'    => 6379,
    'password'    => '',
    'database'    => 0,
    'timeout'     => 0,
    'persistent'  => false,
  ], $conf);
  
  $name = md5(serialize($conf));
  if(empty($_instance[$name])){
    $reds = new Redis();
    $func = $conf['persistent'] ? 'pconnect' : 'connect';
    $retn = $reds->$func($conf['hostname'], $conf['hostport'], $conf['timeout']);
    if ($retn && !empty($conf['password'])) {
      $reds->auth($conf['password']);
    }
    if ($retn && $conf['database'] > 0) {
      $reds->select($conf['database']);
    }
    $_instance[$name] = $reds;
  }
  return $_instance[$name];
}
// UNICODEFFFE UTF-16LE UTF16LE  => CP65001 UTF-8 UTF8
function UTF8_UNICODE($str) {
  return iconv('UTF-8', 'UTF-16LE', $str);
}

function UNICODE_UTF8($str) {
  return iconv('UTF-16LE', 'UTF-8', $str);
}
/**
 *  @brief  : 统一封装API接口
 *  @param [in] $data : 欲返回的数据
 *  @param [in] $code : 错误码
 *  @param [in] $msg  : 错误描述
 *  @param [in] $type : 返回数据格式
 *  @param [in] $header : 发送的`Header`信息
 *  @return : HttpResponseException
 *  @details: 
 */
function result($data=[], $code = 0, $msg = '', $type = '', $header = []) {
  $req = request();
  $retn = [
    'errno' => $code,
    'error' => !empty($msg) ? $msg : ($code == 0 ? '成功' : '失败'),
    'time'  => $req->server('REQUEST_TIME'),
    'data'  => $data,
  ];
  if (empty($type)) {
    $aa = Config::get('var_jsonp_handler');
    $bb = Config::get('default_ajax_return');
    $type = $req->has($aa) ? 'jsonp' : $bb;
  }
  $resp = response($retn, 200, $header, $type);
  return exception($resp, 0, 'think\exception\HttpResponseException');
}
/**
 * 实例化数据库类
 * @param string  $name   指定默认数据表名（含前缀）
 * @param string  $config 数据库配置参数
 * @param bool    $force  是否强制重新连接
 * @return \think\db\Query
 */
function table($name = '', $config = '', $force = false) {
  if (!empty($config) && is_string($config)) {
    $eax = explode('.', $config, 3);
    $ecx = count($eax);
    if ($ecx == 3) { // table('AccountsInfo', 'rydb.accounts.cs')
      $config = Config::get("{$eax[0]}.{$eax[1]}", $eax[2]);
    } else if ($ecx == 2) { // table('AccountsInfo', 'rydb.accounts')
      $config = Config::get($config);
    }
  }
  return Db::connect($config, $force)->table($name);
}

// 第三方登录
function CPP_EfficacyOtherPlatform (
  $PlatformID, // 平台编号, 参考`LOGIN_TYPE`
  $UserUin, // 用户Uin
  $OpenID,  // 用户OpenID
  $NickName, // 用户昵称
  $Gender, // 用户性别 0=未知; 1=男性; 2=女性;
  $ClientIP, // 连接地址
  $MachineID, // 机器标识
  $WXImageURL, // 微信头像地址
  $Channel, // 渠道
  $db = ''  // 默认为空表示按host适配
) {
  
  $Gender = in_array($Gender, [0, 1, 2]) ? $Gender : 0;
  $db = trim($db, '.');
  $db = empty($db) ? '' : ".{$db}";
  try {
    $db = table('', "rydb.accounts{$db}");
    $eax = $db->query("
SET ANSI_NULLS ON
SET ANSI_WARNINGS ON
DECLARE @errno INT, @error NVARCHAR(255)
EXEC @errno = [dbo].[CPP_EfficacyOtherPlatform]
  @cbPlatformID   = ?,
  @szUserUin      = ?,
  @szOpenID       = ?,
  @szNickName     = ?,
  @cbGender       = ?,
  @szClientIP     = ?,
  @szMachineID    = ?,
  @szWXImageURL   = ?,
  @Channel        = ?,
  @szResult       = @error OUTPUT;
SELECT @errno AS errno, @error AS error;
", [
  $PlatformID, $UserUin, $OpenID, trim($NickName), $Gender, $ClientIP, $MachineID, $WXImageURL, $Channel
]);
    $eax = $eax[0];
  } catch (Exception $e) {
    $eax = ['errno' => $e->getCode(), 'error' => $e->getMessage()];
  }
  return $eax;
}
// 玩家与推广员家园关系绑定
function FamilyBind($UserID, $AUID, $db = '') { // $db默认为空表示按host适配
  try {
    $db = trim($db, '.');
    $db = empty($db) ? '' : ".{$db}";
    $db = table('', "rydb.websms{$db}");
    $db->query('EXEC PHP_bindFamily :UserID, :AUID', ['UserID' => $UserID, 'AUID' => $AUID]);
  } catch (Exception $e) {
    $errno = $e->getCode();
    $error = $e->getMessage();
    if (stripos($error, 'The active result for the query contains no fields.') === false) {
      trace(['errno' => $errno, 'error' => $error]);
    }
  }
  return;
}
/**
 *  @brief  : 玩家与推广员代理关系绑定
 *  @param [in] $UserID      : 玩家UserID
 *  @param [in] $AGameID : 推广员的邀请码
 *  @param [in] $KindID : 对应小游戏绑定
 *  @param [in] $db : 默认为空表示按host适配
 *  @return : bool
 *  @details: 
 */
function AgentBind($UserID, $AGameID, $KindID = 0, $db = '') {
  try {
    $db = trim($db, '.');
    $db = empty($db) ? '' : ".{$db}";

    $db = table('', "rydb.accounts{$db}");
    $eax = $db->query("
SET ANSI_NULLS ON
SET ANSI_WARNINGS ON
DECLARE @dwResult INT, @szResult NVARCHAR(255)
EXEC @dwResult = [RYAccountsDB].[dbo].[CPP_BindSpreaderCode]
  @dwUserID = ?,
  @dwCode   = ?,
  @dwKindID = ?,
  @szResult = @szResult OUTPUT;
SELECT @dwResult AS dwResult, @szResult AS szResult;
", [
  $UserID, $AGameID, $KindID
]);
    $eax = $eax[0];
    trace($eax);
  } catch (Exception $e) {
    $errno = $e->getCode();
    $error = $e->getMessage();
    trace(['errno' => $errno, 'error' => $error]);
  }
}
/**
 *  @brief: 辅助函数, 返回`pack/unpack`第一个参数
 *  @param [in] $def  : 固定结构表示的一维数组
 *  @param [in] $pack : true=pack, false=unpack
 *  @return : string
 */
function __struct($def, $pack = true) {
  $eax = '';
  if ($pack == true) { // pack
    foreach($def as $k =>  & $v) {
      $eax = $eax.$v;
    }
  } else { // unpack
    $ebx = [];
    foreach($def as $k => $v) {
      $ebx[] = $v.$k;
    }
    $eax = implode('/', $ebx);
  }
  return $eax;
}
/**
 *  @brief  : 生成唯一订单号(固定18位)
 *  @return : string
 *  @details: 14位YmdHis + 3位随机数 + 1位校验码
 */
function MakeTradeNo() {
  $retn = '';
  $xishu = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
  $yushu = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]; // 余数0-10对应

  $retn = sprintf('%s%03d', date('YmdHis'), mt_rand(0, 999)); // 刚好17位
  $eax = 0;
  for ($i = 0; $i < 17; $i++) {
    $eax += $retn[$i] * $xishu[$i];
  }
  $retn = $retn.$yushu[$eax % 11];
  return $retn;
}
/**
 *  @brief  : 移除`buildSql`产生的多余语句
 *  @param [in] $sql : `buildSql`返回值
 *  @return : string
 *  @detail :
 */
function sql_pure($sql) {
  $sql2 = str_replace(['( SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER ( ORDER BY rand()) AS ROW_NUMBER FROM ', ' AS thinkphp) AS T1 )'], ['', ''], $sql);
  return $sql2;
}
/**
 *  @brief  : 分页类
 *  @param  : $data=数据数组，$curpage=跳转的页码，$row=每页展示的条数，$url=跳转路径
 *  @return : array()  pageobject
 *  @detail :
 */

function paginations($data=[],$curpage,$rows,$url){
    $dataTo = array();
    $dataTo = array_chunk($data,$rows);
    $showdata = array();
    if($dataTo){
        $showdata = $dataTo[$curpage-1];
    }else{
        $showdata = null;
    }
    $p = Bootstrap::make($showdata, $rows, $curpage, count($data), false, [
        'var_page' => 'page',
        'path'     => $url,//这里根据需要修改url
        'query'    => $data,
        'fragment' => '',
    ]);
    $p->appends($_GET);
    return $p;
}

function is_json($str){
    $html = substr($str,0,1);
    if ($html = '{'){
        $json_strs = str_replace('＼＼', '', $str);
        $out_arr = array();
        preg_match('/{.*}/', $json_strs, $out_arr);
        return $out_arr;
    }else if ($html = '['){
        $json_strs = str_replace('＼＼', '', $str);
        $out_arr = array();
        preg_match('/[.*]/', $json_strs, $out_arr);
        return $out_arr;
    }else{
        return $str;
    }
}
